package com.example.demo.service.impl;

import com.example.demo.entity.File;
import com.example.demo.entity.FileNode;
import com.example.demo.entity.Folder;
import com.example.demo.entity.User;
import com.example.demo.exception.BusyException;
import com.example.demo.exception.file.InvalidPathException;
import com.example.demo.mapper.FileMapper;
import com.example.demo.mapper.FolderMapper;
import com.example.demo.service.FolderService;
import com.example.demo.utils.FolderUtils;
import com.example.demo.utils.TreeUtils;
import com.example.demo.utils.UserNameUtils;
import com.jcraft.jsch.SftpException;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

@Service
@Transactional
public class FolderServiceImpl implements FolderService {

    @Resource
    FolderMapper folderMapper;
    @Resource
    FileMapper fileMapper;

    private FolderUtils folderUtils = new FolderUtils();
    private TreeUtils treeUtils=new TreeUtils();
    private UserNameUtils userNameUtils=new UserNameUtils();

    @Override
    public void creatFolder(String path) throws IOException, SftpException {
//        if(!path.endsWith("/")){
//            //文件夹一定要以"/"结尾
//            path+="/";
//        }
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        String username=user.getUsername();



        //在磁盘中新建目录(其位置在该用户的文件夹下)
        String basePath= FolderUtils.basePath +"/"+username;
        folderUtils.createFolder(basePath,path);


        //向数据库中插入文件夹创建者、创建时间和路径
        Folder folder=new Folder();
        folder.setUsername(username);
        folder.setPath(username+"/"+path);
        int res=folderMapper.insertFolder(folder);
        if(res<=0){
            throw new BusyException();
        }
    }

    @Override
    public void uploadFolder(String path, MultipartFile[] files) throws Exception {
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        String username=user.getUsername();
        Folder newFolder=new Folder();
        newFolder.setUsername(username);
        //newFolder.setPath(path);

        //将文件写入磁盘
        //String basePath=FolderUtils.basePath+"/"+username+"/"+type;
        String basePath=FolderUtils.basePath+"/"+username;
        folderUtils.uploadFolder(basePath,path,files);


        //将文件夹以及文件的信息写入数据库
        saveFolderToMysql(username+"/"+path,files,username);

    }

    @Override
    public void saveFolderToMysql(String path, MultipartFile[] files,String username) throws Exception {
        for(MultipartFile myFile :files){
            String pathAll=myFile.getOriginalFilename();
            assert pathAll != null;
            String[] dirs =pathAll.split("/");
            String tmp=path;
            //第一个父级文件夹不能漏掉
            Folder firstFd=folderMapper.selectFolderByPath(tmp);
            if(firstFd==null){
                Folder fd=new Folder();
                fd.setPath(tmp);
                fd.setUsername(username);
                folderMapper.insertFolder(fd);
            }
            for(int i=0;i<dirs.length;i++){
                tmp+="/"+dirs[i];
                Folder folder=folderMapper.selectFolderByPath(tmp);
                if(folder==null){
                    //该文件夹不存在于数据库中则插入
                    Folder fd=new Folder();
                    fd.setPath(tmp);
                    fd.setUsername(username);
                    folderMapper.insertFolder(fd);
                }
//                if(i<dirs.length){
//                    tmp+="/"+dirs[i];
//                }
                if(i==dirs.length-1){
                    //此时的路径不仅是文件夹的，也是文件的，所以需要在文件的数据库中也存入相应信息
                    File file=fileMapper.selectFileByPath(tmp);
                    if(file==null){
                        saveFileToMysql(tmp,myFile,dirs[i]);
                    }
                }
            }
        }
    }

    @Override
    public void saveFileToMysql(String path, MultipartFile file, String title) throws Exception {
        //该文件不存在于数据库中则插入
        File fl=new File();
        fl.setPath(path);
        String size= String.valueOf(file.getSize());
        fl.setSize(size);
        fl.setTitle(title);
        //从文件中读出至多三行为文件的摘要
        java.io.File toFile= FolderUtils.multipartFileToFile(file);
        FileReader reader = new FileReader(toFile);
        BufferedReader br = new BufferedReader(reader);
        String line="";
        StringBuilder summary= new StringBuilder();
        int flag=0;//用于记录摘要的长度，最多不超过原来文件的三行
        while ((line = br.readLine()) != null) {
            // 一次读入一行数据
            summary.append(line);
            flag++;
            if(flag>=3)
                break;
        }
        fl.setSummary(summary.toString());
        fileMapper.insertFileWithSum(fl);
//        File fi=null;
//        fi=fileMapper.selectFileByPath(path);
//        if(fi==null){
//            //如果文件不存在于数据库则插入
//
//        }else {
//            //如果文件存在，则更新;更新的话则上次更新时间也更新
//            fileMapper.updateFileWithSummary(fl);
//        }
    }

    @Override
    public FileNode getFolders(String type) throws SftpException {
        //获取用户名
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
        String username=user.getUsername();

        //根据用户名来找出该用户的文件目录，并且返回一棵树
        return TreeUtils.buildTree(username,type);
    }

    @Override
    public void deleteFolders(String path, String oldType,String newType) throws SftpException, InvalidPathException {

        String username= UserNameUtils.getUsername();
        //path合法性判断
        Folder folder=folderMapper.selectFolderByPath(username+"/"+path);
        if(folder==null){
            throw new InvalidPathException();
        }
        //判断删除的是文件夹还是文件
        File file=fileMapper.selectFileByPath(username+"/"+path);

        String oldPath=FolderUtils.basePath+"/"+username+"/"+path;
        StringBuilder newPath=null;
        if(newType.equals(FolderUtils.trash)){
            newPath= new StringBuilder(FolderUtils.basePath+"/" + username + "/"+newType+"/");
        }else{
            newPath= new StringBuilder(FolderUtils.basePath+"/" + username + "/"+newType+"/");
        }
        //从我的文件夹到回收站>>>>>eg:oldpath:我的文件夹/笔记2 newpath:回收站/
        folderUtils.moveFolder(oldPath,newPath.toString());


        //修改数据库
        String[] tmps=path.split("/");
        int size=tmps.length;
        //先找到该路径的全匹配,修改路径并且置be_delete为1
        StringBuilder newPath2= new StringBuilder(username+"/"+newType+"/"+tmps[size-1]);
        folderMapper.setFolderPathandDelete(username+"/"+path,newPath2.toString());
        //再在原路径后面加“/”，找到原路径下面的文件，修改路径并且置be_delete为1
        Integer len=(username+"/"+path+"/").length()+1;
        newPath2.append("/");
        folderMapper.updateFolderPath(username+"/"+path+"/",newPath2.toString(),len);
        folderMapper.updateFoldersBeDelete(newPath2.toString());
    }

    @Override
    public void renewFolders(String path) throws InvalidPathException, SftpException {
        String username=UserNameUtils.getUsername();
        String sqlPath=username+"/"+path;
        Folder folder=folderMapper.selectFolderByPath(sqlPath);
        //path合法性判断,path为null默认为恢复回收站全部文件

        if(folder==null){
            if(path!=null && !path.equals(""))
            throw new InvalidPathException();
        }
        if(path==null || path.equals("")){
            //恢复回收站下全部文件,末尾一定要加“/",否则会将回收站删除
            sqlPath=username+"/"+FolderUtils.trash+"/";
            Folder[] folders=folderMapper.selectFolderByPrepath(sqlPath);
            for (Folder fd:folders) {
                String newPath=fd.getOldPath();
                String oldPath=fd.getPath();
                newPath=FolderUtils.basePath+"/"+newPath;
                oldPath=FolderUtils.basePath+"/"+oldPath;
                folderUtils.moveFolder(oldPath,newPath);
            }
            folderMapper.renewFolderPath(sqlPath);
            return;
        }
        //找到路径全匹配的恢复路径
        folderUtils.moveFolder(FolderUtils.basePath+"/"+folder.getPath(),FolderUtils.basePath+"/"+folder.getOldPath());
        folderMapper.renewFolderOnePath(sqlPath);
        //原路径后面加“/”，匹配路径下面的文件
        sqlPath+="/";
        Folder[] folders=folderMapper.selectFolderByPrepath(sqlPath);
        for (Folder fd:folders) {
            String newPath=fd.getOldPath();
            String oldPath=fd.getPath();
            newPath=FolderUtils.basePath+"/"+newPath;
            oldPath=FolderUtils.basePath+"/"+oldPath;
            folderUtils.moveFolder(oldPath,newPath);
        }
        folderMapper.renewFolderPath(sqlPath);

    }

    @Override
    public void deleteFolderForever(String path) throws InvalidPathException {
        String username= UserNameUtils.getUsername();
        //路径有效性判断
        String sqlPath=username+"/"+path;
        Folder fd=folderMapper.selectFolderByPath(sqlPath);
        if(fd==null){
            if(!(path==null || path.equals("")))
                throw new InvalidPathException();
        }
        //在磁盘上删除文件/夹
        String realPath=FolderUtils.basePath+"/"+username+"/"+path;
        if(path==null || path.equals("")){
            //清空回收站
            realPath=FolderUtils.basePath+"/"+username+"/"+FolderUtils.trash+"/*";
            folderUtils.deleteFolder(realPath);
            folderMapper.deleteFolder(username+"/"+FolderUtils.trash+"/");
        }else{
            File file=fileMapper.selectFileByPath(path);
            if(file==null){
                folderUtils.deleteFolder(realPath);
                //最后的"/"不可少，否则会将回收站文件夹删除
            }else{
                folderUtils.deleteFile(realPath);
            }
            //在数据库中删除相关数据
            folderMapper.deleteFolder(username+"/"+path);
        }


    }


}
